package cn.jingyuan.swan.hello.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class SocketMultiplexingSingleThread_1 {

    private final boolean runningFlag = true;

    private static final int SERVER_PORT = 9090;

    private Selector selector;

    private ServerSocketChannel server;

    public static void main(String[] args) {
        new SocketMultiplexingSingleThread_1()
            .start();
    }

    public void start() {
        doIniServer();

        doHandler();
    }

    /**
     * 初始化服务端
     */
    public void doIniServer() {
        try {
            selector = Selector.open();

            server = ServerSocketChannel.open();
            server.configureBlocking(false);
            server.bind(new InetSocketAddress(SERVER_PORT));

            server.register(selector, SelectionKey.OP_ACCEPT);

            System.out.println("服务器已启动......");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void doHandler() {
        try {
            while (runningFlag) {
                Set<SelectionKey> keys = selector.keys();
                System.out.println("SelectionKey size:" + keys.size());

                while (selector.select() != 0) {
                    Set<SelectionKey> selectionKeys = selector.selectedKeys();
                    Iterator<SelectionKey> keyIterator = selectionKeys.iterator();

                    while (keyIterator.hasNext()) {
                        SelectionKey selectionKey = keyIterator.next();
                        keyIterator.remove();

                        if (selectionKey.isAcceptable()) {
                            doAspectHandler(selectionKey);
                        } else if (selectionKey.isReadable()) {
                            doReadHandler(selectionKey);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void doAspectHandler(SelectionKey key) throws IOException {
        ServerSocketChannel server = (ServerSocketChannel) key.channel();

        SocketChannel client = server.accept();

        ByteBuffer buffer = ByteBuffer.allocate(8192);

        client.configureBlocking(false);

        client.register(selector, SelectionKey.OP_READ, buffer);

        SocketAddress remoteAddress = client.getRemoteAddress();

        System.out.println("新客户端:" + remoteAddress);
    }

    public void doReadHandler(SelectionKey key) throws IOException {
        SocketChannel client = (SocketChannel) key.channel();

        ByteBuffer buffer = (ByteBuffer) key.attachment();

        buffer.clear();

        int read;

        while (true) {
            read = client.read(buffer);

            if (read > 0) {
                buffer.flip();
                while (buffer.hasRemaining()) {
                    client.write(buffer);
                }
                buffer.clear();
            } else if (read == 0) {
                break;
            } else {
                client.close();
                break;
            }
        }
    }

}
